package com.yellowpage.white.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

public class SqlUtil {

	private final static Logger logger = Logger.getLogger(SqlUtil.class);

	// 数据库联接对象
	private Connection conn = null;

	private SqlUtil() {
		conn = null;
	}

	public static SqlUtil newInstance() {
		return new SqlUtil();
	}

	public void setConnection(String className, String urlOra, String username,
			String password) {
		try {
			logger.info("1111111111111111111111111111111111111");
			Class.forName(className);
			logger.info("2222222222222222222222222222222222222");
			conn = DriverManager.getConnection(urlOra, username, password);
			logger.info("3333333333333333333333333333333333333");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}

	public List executeQuery(String sql, List params) throws Exception {
		logger.info("executeQuery:" + sql);
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		try {

			if (conn == null) {
				throw new Exception("Connection failed.");
			}

			pstmt = conn.prepareStatement(sql);
			if (params != null) {
				for (int k = 0; k < params.size(); k++) {
					pstmt.setObject(k + 1, params.get(k));
				}
			}
			rs = pstmt.executeQuery();
			List vList = new ArrayList();
			ResultSetMetaData aData = rs.getMetaData();
			int column = aData.getColumnCount();
			while (rs.next()) {
				Object[] objs = new Object[column];
				for (int k = 0; k < column; k++) {
					objs[k] = rs.getObject(k + 1);
				}
				vList.add(objs);
			}
			return vList;
		} catch (SQLException e) {
			System.out.println(e.getMessage());
			throw new Exception("err:executeQuery()");
		} finally {
			if (rs != null)
				rs.close();
			if (pstmt != null)
				pstmt.close();
		}
	}

	public int executeUpdate(String sql, List params) throws Exception {
		logger.info("executeQuery:" + sql);
		PreparedStatement pstmt = null;
		int rs = 0;

		try {

			if (conn == null) {
				throw new Exception("Connection failed.");
			}

			pstmt = conn.prepareStatement(sql);
			if (params != null) {
				for (int k = 0; k < params.size(); k++) {
					pstmt.setObject(k + 1, params.get(k));
				}
			}
			rs = pstmt.executeUpdate();

			return rs;
		} catch (SQLException e) {
			throw new Exception("err:executeUpdate()");
		} finally {

			if (pstmt != null)
				pstmt.close();
		}
	}

	/**
	 * 字段为string类型静态常量, 比如char, varchar, varchar2等等
	 */
	public static final int PROPERTY_TYPE_STRING = 0;

	/**
	 * 字段为number类型静态常量, 比如int, number等等
	 */
	public static final int PROPERTY_TYPE_NUMBER = 1;

	/**
	 * 字段为date类型静态常量
	 */
	public static final int PROPERTY_TYPE_DATE = 2;

	/**
	 * 默认字段类型是string
	 * 
	 * @param value
	 * @param propertyName
	 * @param operator
	 * @return
	 */
	public static String parseInputToSQL(String value, String propertyName,
			String operator) {
		return parseInputToSQL(value, propertyName,
				SqlUtil.PROPERTY_TYPE_STRING, operator);
	}
	
	/**
	 * 默认的操作类型是'and'
	 * @param value
	 * @param propertyName
	 * @param propertyType
	 * @return
	 */
	public static String parseInputToSQL(String value, String propertyName, int propertyType) {
		return parseInputToSQL(value, propertyName, propertyType, "and");		
	}

	/**
	 * 
	 * @param value
	 *            客户端传入的输入值
	 * @param propertyName
	 *            数据库或者POJO属性的名称,包括别名,比如'u.userName'
	 * @param propertyType
	 *            数据类型:date, number, string
	 * @param operator
	 *            操作类型,说明该字段和其他字段之间的关系,or 或者 and
	 * @return 可以拚接的sql条件
	 */
	public static String parseInputToSQL(String value, String propertyName,
			int propertyType, String operator) {
		// 如果输入的value是空,那么返回空串
		if (value == null || value.length() == 0)
			return "";

		// 将'转义为''
		value = value.replaceAll("'", "''");

		Pattern p = Pattern.compile(",");
		String[] vs = p.split(value);
		StringBuffer sql = new StringBuffer();
		// 循环检查每一个逗号分隔出的值
		for (int i = 0, j; i < vs.length; i++) {
			// 如果是空的标示符,那么需要查 'xx is null'
			if (vs[i].equalsIgnoreCase("null")) {
				sql.append(propertyName).append(" is null or ");

				// 如果含有..,表示是一个范围的查询, 'xx >= v1 and xx <= v2',v1和v2用..隔开
			} else if ((j = vs[i].indexOf("..")) != -1) {
				String min = vs[i].substring(0, j);
				String max = vs[i].substring(j + 2);
				// 类型是数字类型,不须要加''
				if (propertyType == SqlUtil.PROPERTY_TYPE_NUMBER) {
					sql.append("(").append(propertyName).append(" >= ").append(
							min).append(" and ").append(propertyName).append(
							" <= ").append(max).append(") or ");
					// 类型是日期类型,需要to_date
					// 并且查min值的0:0:0 到max值的23:59:59
				} else if (propertyType == SqlUtil.PROPERTY_TYPE_DATE) {
					sql.append("(").append(propertyName)
							.append(" >= to_date('").append(min).append(
									"', 'yyyy-mm-dd') and ").append(
									propertyName).append(" < to_date('")
							.append(max).append("', 'yyyy-mm-dd') + 1) or ");
					// 类型是字符串类型,需要''
				} else {
					sql.append("(").append(propertyName).append(" >= '")
							.append(min).append("' and ").append(propertyName)
							.append(" <= '").append(max).append("') or ");
				}

				// 剩下就是常规的查询方法
			} else {
				// 字段类型是数字,使用=,并且不使用''
				if (propertyType == SqlUtil.PROPERTY_TYPE_NUMBER) {
					sql.append(propertyName).append(" = ").append(vs[i])
							.append(" or ");
					// 字段是日期,使用to_date进行转型处理
					// 并且必须是输入的值的0:0:0秒到23:59:59秒
				} else if (propertyType == SqlUtil.PROPERTY_TYPE_DATE) {
					sql.append("(").append(propertyName)
							.append(" >= to_date('").append(vs[i]).append(
									"', 'yyyy-mm-dd') and ").append(
									propertyName).append(" < to_date('")
							.append(vs[i]).append("', 'yyyy-mm-dd') + 1) or ");
					// 字段是字符串,使用like,并且需要加''
				} else {

					// 默认使用=链接
					String queryOperation = " = ";
					// 如果有%或者_使用like连接
					if (vs[i].indexOf('%') != -1 || vs[i].indexOf('_') != -1)
						queryOperation = " like ";

					sql.append(propertyName).append(queryOperation + " '")
							.append(vs[i]).append("' or ");
				}

			}

		}// for (int i = 0, j; i < vs.length; i ++)

		// 当返回的sql不是空的情况下
		if (sql.length() != 0) {
			// 去掉多出来的' or '四位
			sql.setLength(sql.length() - 4);
			// 如果不止一个值,需要在整个sql外面包上括号
			if (vs.length > 1)
				sql.insert(0, "(").append(")");
			// 在整个sql的最前加上操作符 and 获取 or
			sql.insert(0, " ").insert(0, operator).insert(0, " ");
		}

		return sql.toString();
	}

	public static void main(String[] as) throws Exception {
		System.out.println(SqlUtil.parseInputToSQL("K5%", "pc1.CODE",0));
	}
}
